/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.mzk.oai.metadataRepository.transformation;

import cz.mzk.oai.metadataRepository.metadata.MetadataFormat;
import cz.mzk.rehan.commons.Dom4jUtils;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.DocumentResult;
import org.dom4j.io.DocumentSource;

/**
 *
 * @author Martin Řehánek (rehan at mzk.cz)
 */
public abstract class XsltSingleSourceConditionedBuilder implements SingleSourceTransformer {

    private static final Map<String, Transformer > transformerMap = new HashMap<String, Transformer>();
    private static final Logger logger = Logger.getLogger(XsltSingleSourceConditionedBuilder.class.getName());
    private final Transformer transformer;
    private final MetadataFormat sourceFormat;
    private final MetadataFormat resultFormat;

    public XsltSingleSourceConditionedBuilder(File xsltFile, MetadataFormat sourceFormat, MetadataFormat resultFormat) throws TransformationException {
        try {
            this.sourceFormat = sourceFormat;
            this.resultFormat = resultFormat;
            this.transformer = initTransformer(xsltFile);
        } catch (Throwable e) {
            throw new TransformationException(e);
        }
    }

    private Transformer initTransformer(File xsltFile) throws TransformerConfigurationException, FileNotFoundException, DocumentException {
        Transformer present = getPresentTransformer(xsltFile);
        if (present == null){
            Transformer loaded = loadNewTransformer(xsltFile);
            addToMap(xsltFile,loaded);
            return loaded;
        }else{
            return present;
        }
    }

    private Transformer getPresentTransformer(File xsltFile) {
        return transformerMap.get(xsltFile.getAbsolutePath());
    }

    private Transformer loadNewTransformer(File xsltFile) throws FileNotFoundException, DocumentException, TransformerConfigurationException {
        Document xsltDoc = Dom4jUtils.loadDocument(xsltFile, true);
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        return transformerFactory.newTransformer(new DocumentSource(xsltDoc));
    }

    private void addToMap(File xsltFile, Transformer newTransformer) {
        transformerMap.put(xsltFile.getAbsolutePath(), newTransformer);
    }

    public MetadataFormat getSourceFormat() {
        return sourceFormat;
    }

    public MetadataFormat getResultFormat() {
        return resultFormat;
    }

    public Document run(Document sourceDocument) {
        if (canBeTransformed(sourceDocument)) {
            return transform(sourceDocument);
        } else {
            return null;
        }
    }

    abstract boolean canBeTransformed(Document sourceDocument);

    private Document transform(Document sourceDocument) {
        try {
            DocumentResult result = new DocumentResult();
            transformer.transform(new DocumentSource(sourceDocument), result);
            return result.getDocument();
        } catch (TransformerException ex) {
            logger.log(Level.SEVERE, null, ex);
            return null;
        }
    }
}
